# -*- coding: utf-8 -*-
import logging
import threading

from scrapy.utils.project import get_project_settings

from zc_core.middlewares.proxies.cached_pool import CachedProxyPool
from zc_core.util.instance_builder import build_instance

logger = logging.getLogger(__name__)


class ProxyFacade(object):
    """代理入口类"""
    _instance_lock = threading.Lock()
    _biz_inited = False

    def __init__(self, settings=None):
        if not self._biz_inited:
            self._biz_inited = True
            if not settings:
                settings = get_project_settings()
            # 代理移除积分阈值（大于0开启，小于等于0关闭）
            self.proxy_score_limit = settings.getint('PROXY_SCORE_LIMIT', 0)
            # 指定代理类对象
            proxy_pool_class = settings.get('PROXY_POOL_CLASS')
            if proxy_pool_class:
                self.pool = build_instance(proxy_pool_class, settings)
            else:
                self.pool = CachedProxyPool(settings)
            self.score_mapper = dict()

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler.settings)

    def __new__(cls, *args, **kwargs):
        if not hasattr(ProxyFacade, "_instance"):
            with ProxyFacade._instance_lock:
                if not hasattr(ProxyFacade, "_instance"):
                    ProxyFacade._instance = object.__new__(cls)
        return ProxyFacade._instance

    def get_proxy(self):
        """获取代理"""
        return self.pool.get_proxy()

    def mark_fail(self, proxy):
        """标记失败：移除代理/积分累计"""
        if proxy:
            proxy = proxy.strip('http://').strip('https://')
        if proxy:
            if self.proxy_score_limit > 0:
                # 开启积分机制
                self._instance_lock.acquire(timeout=30)
                score = self.score_mapper.get(proxy, 0)
                if score >= self.proxy_score_limit:
                    # 失效代理移除
                    self.pool.remove_proxy(proxy)
                    self.score_mapper.pop(proxy, None)
                else:
                    # 积分累加
                    self.score_mapper[proxy] = score + 1
                self._instance_lock.release()
            else:
                self.pool.remove_proxy(proxy)

    def mark_success(self, proxy):
        """标记成功：代理积分重置"""
        if self.score_mapper and proxy in self.score_mapper:
            self.score_mapper[proxy] = 0
